#include "renorm_dia.h"
#include "symconst.h"
#include "misc.h"
#include "reduze.h"
#include <boost/graph/copy.hpp>
graph_sub_term:: graph_sub_term(Graphref_lst dl, dia_ext_legs& dleg)
{
  cout<<dl.size()<<endl;
 Graph &ghj = unwrap_ref(dl.front());
 cout<<*( edges(unwrap_ref(dl.front())).first)<<endl;

 cout<<"constr"<<endl;
 std::vector<field> fg_v =  get_local_ext_fields(*(dl.front().get_pointer()),dleg);
  cout<<"local ext fields "<<fg_v.size()<<endl;

  BOOST_FOREACH(field ff, fg_v)
    {
      cout<<"bfe ex f "<<ff<<endl;
    }
  /// vector of new normalize external for ROOT GRAPH momentums
  exvector vbnm = get_input_momentums_vector(dleg,unwrap_ref(dl.front()));
  cout<<vbnm<<endl;
  exmap uiouio,jkl2;
  exvector l_v;
  /// maps for substituting momentum external for SUBGRAPH
  tie(uiouio,jkl2,l_v) =get_local_mom_subs_map(vbnm); 
  cout<<uiouio <<endl<<jkl2<<endl;
  //  cout<<ex_from_graph(dl.front())<<endl;
 
  Graph g_conv;//=copy_graph(dl.front());
  
  copy_graph(unwrap_ref(dl.front()),g_conv); //standart copy function,may copy to other formats=)
  //   local_mom_subs(g_conv,dleg);
  
  cout<<colors::red<<"PRINTING DL_FRONT"<<colors::def_col<<endl;
  graph_ex_subs(uiouio,g_conv);
  print(g_conv);
  
  ex ret_proj = projector(g_conv,jkl2,fg_v,l_v);
  cout<<"Number of subgraphs: "<<dl.size()<<endl;
  Graphref_lst::iterator iter = ++dl.begin();
  if(dl.size() >1)  get_shrinked_graph(unwrap_ref(*(iter)),unwrap_ref(*(iter--)),ret_proj);

  cout<<"                                                                              Hello world"<<endl;
}

renorm_dia::renorm_dia(Graph& G_in,  map_ext_legs& elmp ):G(G_in), dia_number(get_property(G_in,graph_num))
{
  for(map_ext_legs::iterator it = elmp.begin(); it != elmp.end(); ++it)
    cout<<it->first.first<<"  "<<it->first.second<<" " <<it->second.front().first<<"--"<<it->second.front().second<<endl;
  cout<<"Map printed"<<endl;
  /// Creating external legs map for this diagram
  Graph::vertex_iterator vi,vi_end;
  Graph::edge_iterator ei,ei_end;
  Graph::vertex_descriptor vdtmp;
  for (tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) 
    if(is_external_vert(*vi,G))
      {
        BOOST_FOREACH(mom_field_pair mfp1,elmp[make_pair(dia_number,*vi)])
          {
            dia_legs[*vi].push_back(mfp1);
          }
        cout<<"("<< dia_legs[*vi].front().first<<","<< dia_legs[*vi].front().second<<")";
        G_ext_vert_vector.push_back(*vi);
      }
  cout<<"MAPS EXT TEST: "<<G_ext_vert_vector.size()<<endl;
  int vertex_counter = 0;
  exmap subs_to;          // map to subs like p1=-l1
  exmap subs_from;      // map for back subs like l1 = -p1
  ex all_momentum_sum =0;
  BOOST_FOREACH(Graph::vertex_descriptor vdis, G_ext_vert_vector)
    {
      cout<< "Vertex "<<vdis;
      ex sum_momentum_in_vertex =0;
      BOOST_FOREACH( mom_field_pair m_f, dia_legs[vdis])
        {
          sum_momentum_in_vertex +=m_f.first;
          cout<<m_f.first<<" ";
        }
      //      dia_ext_leg_map[vdis]=make_tuple(sum_momentum_in_vertex)
           cout<<unique_symbols(sum_momentum_in_vertex).front()<<endl;
           /// Last n-th vertex momentum is -(i(1)+...+i(n-1))
           if(vertex_counter == G_ext_vert_vector.size() -1)
             {
               symbol sym_to_subs_back = unique_symbols(sum_momentum_in_vertex).front();
               // cout<<"sym_to_subs_back "<<sym_to_subs_back;
               subs_to[sym_to_subs_back] = lsolve(sum_momentum_in_vertex == -all_momentum_sum ,sym_to_subs_back);     
              dia_legs[vdis].front().first = -all_momentum_sum;
              cout<<"EM: "<<dia_legs[vdis].front().first<<endl;
             }
           else
             {
               all_momentum_sum +=cnst::im[vertex_counter];
               subs_from[cnst::im[vertex_counter]] = sum_momentum_in_vertex;
               //           for(std::list<symbol>::iterator it=unique_symbols(sum_momentum_in_vertex).begin();it!=unique_symbols(sum_momentum_in_vertex).end();++it)
               //             {               cout<<*it<<" ";             }
               symbol sym_to_subs_back = unique_symbols(sum_momentum_in_vertex).front();
               // cout<<"sym_to_subs_back "<<sym_to_subs_back;
               subs_to[sym_to_subs_back] = lsolve(sum_momentum_in_vertex ==cnst::im[vertex_counter] ,sym_to_subs_back);
               dia_legs[vdis].front().first =cnst::im[vertex_counter];  /// Storing sum momentum in first particle!!!!!!!!!
              cout<<"EM: "<<dia_legs[vdis].front().first<<endl;
             }
           vertex_counter++;      
      //cout<<endl;
    }
  cout<<subs_to<<endl<<subs_from<<endl;

  for(dia_ext_legs::iterator it = dia_legs.begin(); it != dia_legs.end(); ++it)
   cout<<it->first<<"  "<<it->second.front().first<<endl;


  graph_ex_subs(subs_to,G);   // substituting  new expressions for external momentum in edges and vertices
  // !!!!!!!!!!!NEED REVIEW!!!!!!!!!!
  /// External legs
  /* for(dia_ext_legs::iterator it = dia_legs.begin(); it != dia_legs.end(); ++it)
   {
    cout<<it->second.first<<"  "<<it->second.second<<endl;
    }*/
  // !!!!!!!!!!!NEED REVIEW!!!!!!!!!!

  print(G);

  ///// output for IBP///
  mincer(G,dia_legs);////////////
  ///////////////////////////
  cout<<"Mincer work fine!!!"<<endl;
  /*  NON MINCER IMPORTANT PART
  Graphref_lst l1 = make_subgraphs(G);

  //Graph::edge_iterator ei,ei_end;
  //  cout<<"dist: "<<std::distance(G.children().first,G.children().second)<<endl;
  //          for(tie(ei,ei_end)=edges(G);ei!=ei_end;++ei)
            //            cout<<"BTEST: "<<unwrap_ref(l1.front()).find_edge(*ei).second<<endl;

  M_list =make_terms(l1);
  cout<<"HARE"<<endl;
  //  cout<<*(edges(unwrap_ref(M_list.front().front())).first)<<endl;
  BOOST_FOREACH(Graphref_lst lg,M_list)
    {
      cout<<lg.size()<<endl;
      //      cout<<*(edges(unwrap_ref(lg.front())).first)<<endl;
      graph_sub_term term_1(lg,dia_legs);
    }
  */
  print(G);
}



